package com.jerkin.dubbo.context;

import com.alibaba.dubbo.common.json.JSON;
import com.alibaba.dubbo.rpc.Result;

import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @version V1.0
 * @ClassName: ExceptionHandleTagAspect
 * @Description:
 * @author: huhongzhi
 * @date: 2020/8/3 22:44
 */
@Aspect
@Order(100)
@EnableAspectJAutoProxy
@Component
public class ExceptionHandleTagAspect {

    @Pointcut("@annotation(com.jerkin.dubbo.context.ExceptionHandleTag)")
    public void handleException() {
    }

    @Around("handleException()")
    public Object dohandleException(ProceedingJoinPoint pjp) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException {
        Object result = null;
//        String key =  pjp.getTarget().getClass().getName() + "#" + pjp.getSignature().getName();
//        ExceptionHandleRo exceptionHandleRo = InitExceptionHandleAnnotaions.getExceptionHandle(key);
        MethodSignature methodSign = (MethodSignature) pjp.getSignature();
        ExceptionHandleTag exceptionHandleTag = methodSign.getMethod().getAnnotation(ExceptionHandleTag.class);
        try {
            result = pjp.proceed();
        } catch (Throwable e) {
            if (isInvoke(e, exceptionHandleTag)) {
                String[] referceMethod = exceptionHandleTag.referenceMethod().split("#");
                String bean = referceMethod[0];
                String method = referceMethod[1];

                Method method1 = pjp.getTarget().getClass().getMethod(method,
                        methodSign.getParameterTypes());
                method1.invoke(BeanHelper.getBean(bean), pjp.getArgs());
            }
        }
        return result;

    }

    public Boolean isInvoke(Throwable e, ExceptionHandleTag exceptionHandleTag) {
        for (Class<? extends Throwable> throwable : exceptionHandleTag.exceptions()) {
            if (e instanceof Throwable) {
                return Boolean.TRUE;
            }
        }
        return Boolean.FALSE;
    }
}
